package com.herohead;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.Collection;

import cryptix.message.EncryptedMessage;
import cryptix.message.EncryptedMessageBuilder;
import cryptix.message.KeyBundleMessage;
import cryptix.message.LiteralMessage;
import cryptix.message.LiteralMessageBuilder;
import cryptix.message.Message;
import cryptix.message.MessageException;
import cryptix.message.MessageFactory;
import cryptix.message.NotEncryptedToParameterException;
import cryptix.openpgp.PGPArmouredMessage;
//import cryptix.openpgp.PGPKeyBundle;
import cryptix.pki.KeyBundle;

/** Webmethods version of PGP
 * there is nothing special in this code to do with
 * webmethods. The other versions actually exited the code
 * if the keys was not found
 * 
 */

public class PGPwm {

	static byte[] b;

	KeyBundle bundle = null;
	Message msg = null;
	MessageFactory mf = null;
	LiteralMessage litmsg = null;
	boolean armourFile = false;
	EncryptedMessage em = null;

	//private static PGPKeyBundle secretBundle;
	//private static PGPKeyBundle publicBundle;



	@SuppressWarnings("rawtypes")
	private void AddKey (String key) throws Error {

		try {

			FileInputStream in = new FileInputStream(key);

			MessageFactory mf = MessageFactory.getInstance("OpenPGP");
			Collection msgs = mf.generateMessages(in);

			KeyBundleMessage kbm = (KeyBundleMessage)msgs.iterator().next();

			bundle = kbm.getKeyBundle();

			in.close();

		} catch (IOException ioe) {
			System.err.println("IOException... You did remember to run the "+
					"GenerateAndWriteKey example first, right?");
			ioe.printStackTrace();
		} catch (NoSuchAlgorithmException me) {
			throw new Error(me + " Cannot find the OpenPGP MessageFactory. "+
					"This usually means that the Cryptix OpenPGP provider is not "+
					"installed correctly.");
		} catch (MessageException me) {
			throw new Error(me + " Reading keybundle failed.");
		} catch (Exception e) {
			throw new Error(e);
		}
	}
	private byte[] armourMessage (Message msg) {

		try {
			PGPArmouredMessage armoured;
			armoured = new PGPArmouredMessage(msg);
			b = armoured.getEncoded();

		} catch (MessageException me) {
			System.err.println("Writing the encrypted message failed.");
			me.printStackTrace();
		}

		return b;
	}

	/**
	 * check for Key File
	 * @param fileName
	 * @return true if file exists
	 */

	public boolean CheckForKeyFile (String fileName) {

		File keyFile = new File(fileName);
		if (keyFile.canRead()) {
			return true;
		} else {
			return false;
		}
	}
	/**
	 * DecryptBytes
	 * @param msgBytes
	 * @param privKey
	 * @return
	 * @throws Error
	 */
	@SuppressWarnings("rawtypes")
	public byte[] DecryptBytes (byte[] msgBytes, String privKey) throws Error {


		//**********************************************************************
		// Dynamically register both the Cryptix JCE and Cryptix OpenPGP
		// providers.
		//**********************************************************************
		java.security.Security.addProvider(new cryptix.jce.provider.CryptixCrypto() );
		java.security.Security.addProvider(new cryptix.openpgp.provider.CryptixOpenPGP() );


		//**********************************************************************
		// First read the key.
		//**********************************************************************
		KeyBundle bundle = null;
		MessageFactory mf = null;

		try {

			FileInputStream in = new FileInputStream(privKey);

			mf = MessageFactory.getInstance("OpenPGP");
			Collection msgs = mf.generateMessages(in);

			KeyBundleMessage kbm = (KeyBundleMessage)msgs.iterator().next();

			bundle = kbm.getKeyBundle();

			in.close();

		} catch (IOException ioe) {
			throw new Error("Reading key error");
		} catch (NoSuchAlgorithmException nsae) {
			throw new Error("Cannot find the OpenPGP MessageFactory. "+
					"This usually means that the Cryptix OpenPGP provider is not "+
					"installed correctly.");
		} catch (MessageException me) {
			throw new Error(me + " Reading keybundle failed.");
		} catch (Exception e) {
			throw new Error(e);
		}

		//**********************************************************************
		//  Read the message.
		//**********************************************************************
		EncryptedMessage em = null;

		try {
			DataInputStream in = new DataInputStream(new ByteArrayInputStream(msgBytes));
			Collection msgs = mf.generateMessages(in);
			em = (EncryptedMessage)msgs.iterator().next();
			in.close();

		} catch (IOException ioe) {
			System.err.println("IOException... You did remember to run the "+
					"Encrypt example first, right?");
			ioe.printStackTrace();
		} catch (MessageException me) {
			throw new Error(me + " Reading message failed.");
		} catch (Exception e) {
			throw new Error(e);
		}
		//**********************************************************************
		// Decrypt the message.
		//**********************************************************************
		try {

			Message msg = em.decrypt(bundle, "TestingPassphrase".toCharArray());

			b = (((LiteralMessage)msg).getBinaryData());



		} catch (NotEncryptedToParameterException me) {
			throw new Error(me + " Not encrypted to this key.");
		} catch (UnrecoverableKeyException me) {
			throw new Error(me + " Invalid passphrase.");
		} catch (MessageException me) {
			throw new Error(me + " Decrypting message failed.");
		} catch (IllegalArgumentException me) {
			throw new Error(me + " Private key not found");
		} catch (Exception e) {
			throw new Error(e);
		}

		return b;
	}

	/**
	 * Encrypt bytes and return encrypted bytes
	 * @param msgBytes
	 * @param pubKey
	 * @return encrypted bytes
	 */
	public byte[] EncryptBytes (byte[] msgBytes, String pubKey) throws Error {
		//**********************************************************************
		// Dynamically register both the Cryptix JCE and Cryptix OpenPGP
		// providers.
		//**********************************************************************
		java.security.Security.addProvider(
				new cryptix.jce.provider.CryptixCrypto() );
		java.security.Security.addProvider(
				new cryptix.openpgp.provider.CryptixOpenPGP() );

		AddKey(pubKey);
		msg = EncryptMessage(msgBytes);

		try {

			if (armourFile) {
				b = armourMessage(msg);
			} else {
				b = msg.getEncoded();
			}
		} catch (MessageException me) {
			throw new Error(me + ":Reading message failed");
			//System.err.println("Reading message failed.");
			//me.printStackTrace();
			//System.exit(-1);
		}
		return b;
	}
	private Message EncryptMessage (byte[] msgBytes) throws Error {
		//**********************************************************************
		//  Build the literal message.
		//**********************************************************************

		try {
			LiteralMessageBuilder lmb =	LiteralMessageBuilder.getInstance("OpenPGP");
			lmb.init(msgBytes);
			litmsg = (LiteralMessage)lmb.build();
		} catch (NoSuchAlgorithmException me) {
			System.err.println(me + " Cannot find the OpenPGP LiteralMessageBuilder."+
					" This usually means that the Cryptix OpenPGP provider is not "+
					"installed correctly.");
			me.printStackTrace();
		} catch (MessageException me) {
			throw new Error(me + " Creating the literal message failed.");
			//System.err.println("Creating the literal message failed.");
			//me.printStackTrace();
		} catch (Exception e) {
			throw new Error(e);
		}
		//**********************************************************************
		// Encrypt the message.
		//**********************************************************************
		try {

			EncryptedMessageBuilder emb = EncryptedMessageBuilder.getInstance("OpenPGP");
			emb.init(litmsg);
			emb.addRecipient(bundle);
			emb.setAttribute("compressed", "true");
			msg = emb.build();

		} catch (NoSuchAlgorithmException me) {
			throw new Error(me + " Cannot find the OpenPGP "+
					"EncryptedMessageBuilder. "+
					"This usually means that the Cryptix OpenPGP provider is not "+
					"installed correctly.");
		} catch (MessageException me) {
			throw new Error(me + " Creating the encrypted message failed.");
			//System.err.println("Creating the encrypted message failed.");
			//me.printStackTrace();
		} catch (Exception e) {
			throw new Error(e);
		}
		return msg;
	}

	public boolean GetArmour () {
		return armourFile;
	}
	public void SetArmour(boolean armourValue) {
		armourFile = armourValue;
	}
}